
// #include "common.h"
#include "draw.h"
#include "util.h"
#include "resources.h"
#include "animation.h"
#include "oled.h"

inline static void setBuffByte(uint8_t *, uint8_t, uint8_t, uint8_t);
inline uint8_t pgm_read_byte(const uint8_t *abc) { return *abc; }

void draw_string(char *string, bool invert, uint8_t x, uint8_t y)
{
    uint8_t charCount = 0;

    while (*string)
    {
        char c = *string - ' ';     // 32 is the space character 使用的是smallFont 字库
        if (c >= 95)
            c = 0;
        uint8_t xx = x + (charCount * 7);
        draw_bitmap(xx, y, smallFont[(uint8_t)c], SMALLFONT_WIDTH, SMALLFONT_HEIGHT, invert, 0);
        if (invert)
        {
            if (xx > 0)
                setBuffByte(oledBuffer, xx - 1, y, 0xFF);
            if (xx < FRAME_WIDTH - 5)
                setBuffByte(oledBuffer, xx + 5, y, 0xFF);
        }
        string++;
        charCount++;
    }
}

void draw_string_P(const char *string, bool invert, uint8_t x, uint8_t y)
{
    uint8_t len = strlen(string);
    char buff[len + 1];
    strcpy(buff, string);
    draw_string(buff, invert, x, y);
}

inline static void setBuffByte(uint8_t *buff, uint8_t x, uint8_t y, uint8_t val)
{
    unsigned short pos = x + (y / 8) * FRAME_WIDTH;
    buff[pos] |= val;
}

inline static uint8_t readPixels(const uint8_t *loc, bool invert)
{
    // uint8_t pixels = ((int)loc & 0x8000 ? eeprom_read_uint8_t((int)loc & ~0x8000) : pgm_read_byte(loc));
    uint8_t pixels = pgm_read_byte(loc); // d读取flash里面的数据到ram
    if (invert)
        pixels = ~pixels;
    return pixels;
}

// 绘制图形
// x, y - 图片的左上角坐标
// bitmap - 图片的指针
// w, h - 图片的宽和高
// invert - 图片是否反转
// offsetY - 图片的偏移量
void draw_bitmap(uint8_t x, uint8_t yy, const uint8_t *bitmap, uint8_t w, uint8_t h, bool invert, uint8_t offsetY)
{
    // Apply animation offset
    yy += animation_offsetY();

    //
    uint8_t y = yy - offsetY;   // 计算图片起始位置y坐标

    //
    uint8_t h2 = h / 8;     //计算图片使用的字节数

    //
    uint8_t pixelOffset = (y % 8);  // 计算出图片多出部分

    uint8_t thing3 = (yy + h);      // 计算出图片最后一行Y坐标

    //
    for(uint8_t hh=0;hh<h2;hh++)        // #define LOOP(count, var) for(uint8_t var=0;var<count;var++)
    {
        //
        uint8_t hhh = (hh * 8) + y; // Current Y pos (every 8 pixels)
        uint8_t hhhh = hhh + 8;     // Y pos at end of pixel column (8 pixels)

        //
        if (offsetY && (hhhh < yy || hhhh > FRAME_HEIGHT || hhh > thing3))
            continue;

        //
        uint8_t offsetMask = 0xFF;
        if (offsetY)
        {
            if (hhh < yy)
                offsetMask = (0xFF << (yy - hhh));
            else if (hhhh > thing3)
                offsetMask = (0xFF >> (hhhh - thing3));
        }

        unsigned short aa = ((hhh / 8) * FRAME_WIDTH);

        const uint8_t *b = bitmap + (hh * w);

        // If() outside of loop makes it faster (doesn't have to keep re-evaluating it)
        // Downside is code duplication
        if (!pixelOffset && hhh < FRAME_HEIGHT)
        {
            //
            LOOP(w, ww)
            {
                // Workout X co-ordinate in frame buffer to place next 8 pixels
                uint8_t xx = ww + x;

                // Stop if X co-ordinate is outside the frame
                if (xx >= FRAME_WIDTH)
                    continue;

                // Read pixels
                uint8_t pixels = readPixels(b + ww, invert) & offsetMask;

                oledBuffer[xx + aa] |= pixels;

                // setBuffByte(buff, xx, hhh, pixels, colour);
            }
        }
        else
        {
            unsigned short aaa = ((hhhh / 8) * FRAME_WIDTH);

            //
            LOOP(w, ww)
            {
                // Workout X co-ordinate in frame buffer to place next 8 pixels
                uint8_t xx = ww + x;

                // Stop if X co-ordinate is outside the frame
                if (xx >= FRAME_WIDTH)
                    continue;

                // Read pixels
                uint8_t pixels = readPixels(b + ww, invert) & offsetMask;

                //
                if (hhh < FRAME_HEIGHT)
                    oledBuffer[xx + aa] |= pixels << pixelOffset;
                // setBuffByte(buff, xx, hhh, pixels << pixelOffset, colour);

                //
                if (hhhh < FRAME_HEIGHT)
                    oledBuffer[xx + aaa] |= pixels >> (8 - pixelOffset);
                // setBuffByte(buff, xx, hhhh, pixels >> (8 - pixelOffset), colour);
            }
        }
    }
}

// y must be a multiple of 8
// height is always 8
void draw_clearArea(uint8_t x, uint8_t y, uint8_t w)
{
    unsigned short pos = x + (y / 8) * FRAME_WIDTH;
    memset(&oledBuffer[pos], 0x00, w);
}

void draw_end()
{
    oled_refresh_gram(); // 刷新屏幕的意思
}
